/******************************************************************************
 Copyright (c) 2024-2025 Qualcomm Technologies International, Ltd.
 All Rights Reserved.
 Qualcomm Technologies International, Ltd. Confidential and Proprietary.

******************************************************************************/

#include "gatt_ras_server_private.h"

#ifdef INSTALL_CHANNEL_SOUNDING_SUPPORT
#include "gatt_ras_server_debug.h"
#include "gatt_ras_server_notify_indicate.h"
#include "gatt_ras_server_access.h"

/***************************************************************************
NAME
    sendRasServerIndication

DESCRIPTION
    Sends an indication to the GATT library.
*/
static void sendRasServerIndication(CsrBtGattId gattId,
                                          connection_id_t cid,
                                          uint16 handle,
                                          uint16 sizeValue,
                                          uint8 *const value)
{
    uint8* data;

    data = (uint8*)CsrPmemZalloc(sizeof(uint8)*sizeValue);
    CsrMemCpy(data, value, sizeValue);

    if ( cid == GATT_RAS_SERVER_INVALID_ZERO_CID )
    {
        GATT_RAS_SERVER_PANIC("PACS: No Cid!\n");
    }
    else
    {

        if (sizeValue == 2)
        {
            GATT_RAS_SERVER_DEBUG("cid: %x >> 0x%x 0x%x \n", cid, value[0], value[1]);
        }
        else if (sizeValue == 3)
        {
            GATT_RAS_SERVER_DEBUG("cid: %x >> 0x%x 0x%x 0x%x \n", cid, value[0],
                value[1], value[2]);
        }
        else if (sizeValue == 5)
        {
            GATT_RAS_SERVER_DEBUG("cid: %x >> 0x%x 0x%x 0x%x 0x%x 0x%x \n", cid, value[0],
                value[1], value[2], value[3], value[4]);
        }

        CsrBtGattIndicationEventReqSend(gattId,
                                        cid,
                                        handle,
                                        sizeValue,
                                        data);
    }
}

/***************************************************************************
NAME
    sendRasServerNotification

DESCRIPTION
    Sends an notification to the GATT library.
*/
static void sendRasServerNotification(CsrBtGattId task,
                                             ConnectionIdType cid,
                                             uint16 handle,
                                             uint16 size_value,
                                             const uint8 *value)
{
    uint8* data;

    data = (uint8*)CsrPmemZalloc(size_value);
    CsrMemCpy(data, value, size_value);

    if ( cid == GATT_RAS_SERVER_INVALID_ZERO_CID )
    {
        GATT_RAS_SERVER_PANIC(
                    "RAS: No Cid!\n"
                    );
    }
    else
    {
        if (size_value == 2)
        {
            GATT_RAS_SERVER_INFO("cid: %x Ranging Counter:>> 0x%x 0x%x \n", cid, value[0], value[1]);
        }

        CsrBtGattNotificationEventReqSend(task,
                                          cid,
                                          handle,
                                          size_value,
                                          data);
    }
}

void rasServerSendRasData(GRASS_T *rasSrver,
                                ConnectionIdType cid,
                                uint16 handle,
                                uint16 sizeValue,
                                uint8 *const value)
{
    uint16 client_config = 0;
    uint8 index_client = rasServerGetCidIndex(rasSrver,cid);

    if(handle == HANDLE_ONDEMAND_RANGING_DATA)
    {
      client_config =
           GET_RAS_CLIENT_CONFIG(rasSrver->data.connectedClients[index_client].clientCfg.onDemandDataClientCfg);
    }
    else if (handle == HANDLE_RAS_CONTROL_POINT)
    {
      client_config =
          GET_RAS_CLIENT_CONFIG(rasSrver->data.connectedClients[index_client].clientCfg.controlPointClientCfg);
    }
    else if (handle == HANDLE_REALTIME_RANGING_DATA)
    {
      client_config =
          GET_RAS_CLIENT_CONFIG(rasSrver->data.connectedClients[index_client].clientCfg.realTimeDataClientCfg);
    }
    else if (handle == HANDLE_RANGING_DATA_READY)
    {
      client_config =
          GET_RAS_CLIENT_CONFIG(rasSrver->data.connectedClients[index_client].clientCfg.dataReadyClientCfg);
    }
    else if (handle == HANDLE_RANGING_DATA_OVERWRITTEN)
    {
      client_config =
          GET_RAS_CLIENT_CONFIG(rasSrver->data.connectedClients[index_client].clientCfg.dataOverwrittenClientCfg);
    }

    if ((client_config == GATT_RAS_CLIENT_CONFIG_MASK) || 
         (client_config == GATT_RAS_SERVER_CCC_NOTIFY))
    {
        /* When both are configured, RAS server will only notify */
        sendRasServerNotification(rasSrver->gattId,
                                  cid,
                                  handle,
                                  sizeValue,
                                  value);
    }
    else if (client_config == GATT_RAS_SERVER_CCC_INDICATE)
    {
        sendRasServerIndication(rasSrver->gattId,
                                cid,
                                handle,
                                sizeValue,
                                value);
    }
}

void rasServerRasCpCompleteRangingDataResponse(GRASS_T *rasSrver,
                                                           ConnectionIdType cid,
                                                           uint16 rangingCounter)
{
    uint8 value[GATT_RAS_CP_CRDR_SIZE];
    uint8 clientIndex = rasServerGetCidIndex(rasSrver, cid);

    if (clientIndex == GATT_RAS_SERVER_INVALID_CID_INDEX)
    {
        GATT_RAS_SERVER_ERROR("RAS: Invalid Index!\n");
        return;
    }

    GATT_RAS_SERVER_INFO("controlPointClientCfg: 0x%x",rasSrver->data.connectedClients[clientIndex].clientCfg.controlPointClientCfg);

    if (rasSrver->data.connectedClients[clientIndex].clientCfg.controlPointClientCfg == GATT_RAS_SERVER_CCC_INDICATE)
    {
        value[0] = GATT_RAS_CMPLT_RANGING_DATA_RESPONSE;
        value[1] = (rangingCounter & 0x00FF);
        value[2] = ((rangingCounter & 0xFF00) >> 8);

        sendRasServerIndication(
            rasSrver->gattId,
            rasSrver->data.connectedClients[clientIndex].cid,
            HANDLE_RAS_CONTROL_POINT,
            GATT_RAS_CP_CRDR_SIZE,
            value);
    }
}

void rasServerRasCpCmpLostRangingDataSegResponse(GRASS_T *rasSrver,
                                                             ConnectionIdType cid,
                                                             uint16 rangingCounter,
                                                             uint8 startSegment,
                                                             uint8 endSegment)
{

    uint8 clientIndex = rasServerGetCidIndex(rasSrver, cid);

    if (clientIndex == GATT_RAS_SERVER_INVALID_CID_INDEX)
    {
        GATT_RAS_SERVER_ERROR("RAS: Invalid Index!\n");
        return;
    }

    GATT_RAS_SERVER_INFO("controlPointClientCfg: 0x%x",rasSrver->data.connectedClients[clientIndex].clientCfg.controlPointClientCfg);

    if (rasSrver->data.connectedClients[clientIndex].clientCfg.controlPointClientCfg == GATT_RAS_SERVER_CCC_INDICATE)
    {
        uint8 value[GATT_RAS_CP_CLRDSR_SIZE];

        value[0] = GATT_RAS_CMPLT_LOST_RANGING_DATA_SEG_RESPONSE;
        value[1] = (rangingCounter & 0x00FF);
        value[2] = ((rangingCounter & 0xFF00) >> 8);
        value[3] = startSegment;
        value[4] = endSegment;

        sendRasServerIndication(
            rasSrver->gattId,
            rasSrver->data.connectedClients[clientIndex].cid,
            HANDLE_RAS_CONTROL_POINT,
            GATT_RAS_CP_CLRDSR_SIZE,
            value);
    }
}

void rasServerRasCpResponseCode(GRASS_T *rasSrver,
                                       ConnectionIdType cid,
                                       gattRasServerResponseCode responseCode)
{

    uint8 clientIndex = rasServerGetCidIndex(rasSrver, cid);

    if (clientIndex == GATT_RAS_SERVER_INVALID_CID_INDEX)
    {
        GATT_RAS_SERVER_ERROR("RAS: Invalid Index!\n");
        return;
    }

    GATT_RAS_SERVER_INFO("controlPointClientCfg: 0x%x",rasSrver->data.connectedClients[clientIndex].clientCfg.controlPointClientCfg);

    if (rasSrver->data.connectedClients[clientIndex].clientCfg.controlPointClientCfg == GATT_RAS_SERVER_CCC_INDICATE)
    {
        uint8 value[GATT_RAS_CP_RC_SIZE];

        value[0] = GATT_RAS_RESPONSE_CODE;
        value[1] = (uint8) responseCode;

        sendRasServerIndication(
            rasSrver->gattId,
            rasSrver->data.connectedClients[clientIndex].cid,
            HANDLE_RAS_CONTROL_POINT,
            GATT_RAS_CP_RC_SIZE,
            value);
    }
}

#endif /* INSTALL_CHANNEL_SOUNDING_SUPPORT */